package edu.study.user.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import edu.study.api.common.dto.BaseRespDto;
import edu.study.api.common.dto.RespDto;
import edu.study.api.common.enums.BaseResultCodeEnum;
import edu.study.api.common.enums.StatusTypeEnum;
import edu.study.common.util.BeanCopy;
import edu.study.common.util.PasswordUtil;
import edu.study.common.util.cache.Cache;
import edu.study.user.api.dto.AuthDto;
import edu.study.user.api.dto.DepartmentAndSubDto;
import edu.study.user.api.dto.DepartmentRoleAuthDto;
import edu.study.user.api.dto.RoleUserDto;
import edu.study.user.api.dto.UserDetailDto;
import edu.study.user.api.dto.UserDto;
import edu.study.user.api.req.user.AddUserReq;
import edu.study.user.api.req.user.LoginReq;
import edu.study.user.api.req.user.ModifyPasswordReq;
import edu.study.user.api.req.user.QueryUserListReq;
import edu.study.user.api.req.user.QueryUserReq;
import edu.study.user.config.UserConstant;
import edu.study.user.dao.mapperExt.AuthDOMapperExt;
import edu.study.user.dao.mapperExt.DepartmentDOMapperExt;
import edu.study.user.dao.mapperExt.DepartmentUserDOMapperExt;
import edu.study.user.dao.mapperExt.RoleDOMapperExt;
import edu.study.user.dao.mapperExt.RoleUserDOMapperExt;
import edu.study.user.dao.mapperExt.UserDOMapperExt;
import edu.study.user.dbBean.DepartmentDO;
import edu.study.user.dbBean.DepartmentUserDO;
import edu.study.user.dbBean.RoleDO;
import edu.study.user.dbBean.RoleUserDO;
import edu.study.user.dbBean.UserDO;
import edu.study.user.util.UserUtils;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class UserService {

    @Autowired
    private UserDOMapperExt userDOMapperExt;
    
    @Autowired
	private DepartmentDOMapperExt departmentDOMapperExt;
    
    @Autowired
	private RoleDOMapperExt roleDOMapperExt;
    
    @Autowired
	private DepartmentUserDOMapperExt departmentUserDOMapperExt;
    
    @Autowired
	private RoleUserDOMapperExt roleUserDOMapperExt;
        
    @Autowired
	private AuthDOMapperExt authDOMapperExt;

    @Autowired
    private Cache cache;

    @Autowired
    private UserConstant userConstant;
    
    @Autowired
	private TransactionTemplate transactionTemplate;
    
    @Autowired
	private DepartmentService departmentService;
    
    public BaseRespDto addUser(AddUserReq req) {
        BaseRespDto resp = new BaseRespDto();
        
        DepartmentDO departmentDO = departmentDOMapperExt.queryByDepartmentNo(req.getDepartmentNo());
		if(departmentDO == null) {
			log.info("UserService.addUser, 部门不存在! departmentNo={}", req.getDepartmentNo());
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
		RoleDO roleDO = roleDOMapperExt.queryByRoleNo(req.getRoleNo());
		if(roleDO == null) {
			log.info("UserService.addUser, 角色不存在! roleNo={}", req.getRoleNo());
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
		
        UserDO userDO = userDOMapperExt.queryByLoginName(req.getLoginName());
        if(userDO != null) {
        	log.info("UserService.addUser, 用户已存在! loginName={}", req.getLoginName());
            resp.setResultFail(BaseResultCodeEnum.RECORD_ALREADY_EXISTS);
            return resp;
        }
        
        UserDO newUserDO = new UserDO();
        BeanCopy.copyFromSrcToDest(req, newUserDO);
        String userNo = cache.generateStr("userNo_", 1, null);
        newUserDO.setUserNo(userNo);
        UserDetailDto userDetailDto = UserUtils.getCurrentUser();
		if(userDetailDto!=null) {
			newUserDO.setCreator(userDetailDto.getLoginName());
		}
        String password = PasswordUtil.getMd5Encode(userConstant.getMd5Salt()+userConstant.getPassword());
        newUserDO.setPassword(password);
        
        DepartmentUserDO departmentUserDO = new DepartmentUserDO();
        departmentUserDO.setDepartmentNo(req.getDepartmentNo());
        departmentUserDO.setUserNo(userNo);
        departmentUserDO.setDepartmentUserNo(req.getDepartmentUserNo());
        if(userDetailDto!=null) {
        	departmentUserDO.setCreator(userDetailDto.getLoginName());
		}
        
        RoleUserDO roleUserDO = new RoleUserDO();
        roleUserDO.setRoleNo(req.getRoleNo());
        roleUserDO.setUserNo(userNo);
        if(userDetailDto!=null) {
        	roleUserDO.setCreator(userDetailDto.getLoginName());
		}
        
        Boolean flag = transactionTemplate.execute(new TransactionCallback<Boolean>() {
			@Override
			public Boolean doInTransaction(TransactionStatus arg0) {
				userDOMapperExt.insertSelective(newUserDO);
				departmentUserDOMapperExt.insertSelective(departmentUserDO);
				roleUserDOMapperExt.insertSelective(roleUserDO);
				return true;
			}
		});
        if (!flag) {
			resp.setResultFail(BaseResultCodeEnum.DB_ERROR);
			return resp;
		}
        return resp;
    }
    
    public RespDto<UserDetailDto> login(LoginReq req) {
        RespDto<UserDetailDto> resp = new RespDto<UserDetailDto>();
        UserDO userDO = userDOMapperExt.queryByLoginName(req.getLoginName());
        //用户名密码混淆提示出来
        if(userDO == null) {
        	log.info("UserService.login, loginName={}, 登录名错误!", req.getLoginName());
            resp.setResultFail(BaseResultCodeEnum.LOGIN_NAME_OR_PWD_ERROR);
            return resp;
        }
        boolean flag = PasswordUtil.comparePwd(userConstant.getMd5Salt()+req.getPassword(), userDO.getPassword());
        if(!flag) {
        	log.info("UserService.login, loginName={}, 密码错误!", req.getLoginName());
            resp.setResultFail(BaseResultCodeEnum.LOGIN_NAME_OR_PWD_ERROR);
            return resp;
        }
        UserDetailDto userDetailDto = new UserDetailDto();
        BeanCopy.copyFromSrcToDest(userDO, userDetailDto);
        resp.setData(userDetailDto);
        
        //非超级管理员，查询用户详细信息
        if(StatusTypeEnum.Y.getCode().equals(userDO.getIsRoot())) {
        	return resp;
        }
        
        List<RoleUserDto> roleUserDtoList = roleUserDOMapperExt.queryRoleUserList(null, userDO.getUserNo());
    	if(!CollectionUtils.isEmpty(roleUserDtoList)) {
    		List<DepartmentRoleAuthDto> departmentRoleAuthList = new ArrayList<DepartmentRoleAuthDto>(roleUserDtoList.size());
    		for (RoleUserDto roleUserDto : roleUserDtoList) {
    			DepartmentRoleAuthDto departmentRoleAuthDto = new DepartmentRoleAuthDto();
    			RoleDO roleDO = roleDOMapperExt.queryByRoleNo(roleUserDto.getRoleNo());
    			if(roleDO!=null){
    				departmentRoleAuthDto.setDepartmentNo(roleDO.getDepartmentNo());
    				departmentRoleAuthDto.setRoleNo(roleDO.getRoleNo());
    			}
    			List<AuthDto> authDtoList = authDOMapperExt.queryByRoleNo(roleUserDto.getRoleNo());
				departmentRoleAuthDto.setAuthDtoList(authDtoList);
				departmentRoleAuthList.add(departmentRoleAuthDto);
			}
    		userDetailDto.setDepartmentRoleAuthList(departmentRoleAuthList);
    	}
        return resp;
    }
    
    public BaseRespDto modifyPassword(ModifyPasswordReq req) {
        BaseRespDto resp = new BaseRespDto();
        UserDO userDO = userDOMapperExt.queryByLoginName(req.getLoginName());
        if(userDO == null) {
            resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
            return resp;
        }
        boolean flag = PasswordUtil.comparePwd(userConstant.getMd5Salt()+req.getOldPassword(), userDO.getPassword());
        if(!flag) {
            resp.setResultFail(BaseResultCodeEnum.OLD_PWD_ERROR);
            return resp;
        }
        UserDO newUserDO = new UserDO();
        newUserDO.setId(userDO.getId());
        String newPassword = PasswordUtil.getMd5Encode(userConstant.getMd5Salt()+req.getNewPassword());
        newUserDO.setPassword(newPassword);
        userDOMapperExt.updateByPrimaryKeySelective(newUserDO);
        return resp;
    }
    
    public RespDto<UserDto> queryUser(QueryUserReq req) {
        RespDto<UserDto> resp = new RespDto<UserDto>();
        
        UserDO userDO = userDOMapperExt.queryByUserNo(req.getUserNo());
        if (userDO == null) {
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
        UserDto userDto = new UserDto();
		BeanCopy.copyFromSrcToDest(userDO, userDto);
		resp.setData(userDto);
		return resp;
    }
    
    public RespDto<List<UserDto>> queryUserList(QueryUserListReq req) {
        RespDto<List<UserDto>> resp = new RespDto<List<UserDto>>();
        
        if(StringUtils.isEmpty(req.getRoleNo()) && StringUtils.isEmpty(req.getDepartmentNo()) && StringUtils.isEmpty(req.getParentDepartmentNo())) {
        	resp.setResultFail(BaseResultCodeEnum.INVALID_REQUEST_PARAM);
			return resp;
        }
        if(!StringUtils.isEmpty(req.getRoleNo())) {
        	List<UserDto> list = userDOMapperExt.queryByRoleNo(req.getRoleNo());
        	resp.setData(list);
        	return resp;
        }
        if(!StringUtils.isEmpty(req.getDepartmentNo())) {
        	List<UserDto> list = userDOMapperExt.queryByDepartmentNo(req.getDepartmentNo());
        	resp.setData(list);
        	return resp;
        }
        
        if(!StringUtils.isEmpty(req.getParentDepartmentNo())) {
        	List<UserDto> userDtoList = userDOMapperExt.queryByDepartmentNo(req.getParentDepartmentNo());
        	
        	DepartmentAndSubDto departmentAndSubDto = new DepartmentAndSubDto();
    		departmentAndSubDto.setDepartmentNo(req.getParentDepartmentNo());
    		DepartmentAndSubDto departmentAndSubDtoAll = departmentService.querySubDepartment(departmentAndSubDto);
        	this.departmentAndSubUserDtoList(departmentAndSubDtoAll, userDtoList);
        	
        	resp.setData(userDtoList);
        	return resp;
        }
        return resp;
    }

    /**
     * 查访所有子部门的用户
     */
	private void departmentAndSubUserDtoList(DepartmentAndSubDto departmentAndSubDto, List<UserDto> userDtoList) {
		if(!CollectionUtils.isEmpty(departmentAndSubDto.getSubDepartmentList())) {
			for (DepartmentAndSubDto item : departmentAndSubDto.getSubDepartmentList()) {
				List<UserDto> list = userDOMapperExt.queryByDepartmentNo(item.getDepartmentNo());
				userDtoList.addAll(list);
				this.departmentAndSubUserDtoList(item, userDtoList);
			}
		}
	}
}
